#! /usr/bin/python
# - coding: utf-8 -*-

# Copyright (c) 2007-2008 Renato Chencarek. All rights reserved.
#
# Author: Renato Chencarek <renato.chencarek@gmail.com>
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED,
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

import re
from common import *

import curl, pycurl, tempfile
import os, sys, zipfile, popen2
from crontab import CronTab
from bitps3.encoder import run_encoder, is_encoder_running

INFO_NAME      = 0
INFO_NAME_PT   = 1
INFO_RELEASE   = 2
INFO_NUMCDS    = 3
INFO_FPS       = 4
INFO_SIZE      = 5
INFO_DOWNLOADS = 6
INFO_FLAG      = 7

Log = None

def login_legendas_tv (crl, username, password):
    global Log

    try:
        Log("Logging into http://legendas.tv")
        crl.post("login_verificar.php",
                 (("txtLogin", username),
                  ("txtSenha", password)))
        return "Bem vindo" in crl.body()

    except:
        Log("Exception in login_legendas")
        return False

def search_subtitle(crl, release, language):
    global Log

    try:
        Log("Searching subtitle")

        crl.post("index.php?opcao=buscarlegenda",
                 (('txtLegenda', release),
                  ('selTipo', 1), ('int_idioma', language)))

        data = crl.body()
        subs =  re.findall(".*abredown\(\'(.+)'\).*", data)
        downloads = re.findall(".*Downloads: </b> (\d+) <b>.*", data)
        params = re.findall(".*gpop\((.+)\\\' border.*", data)

        info = []
        for p in params:
            info.append([s.strip("'") for s in p.split(',')])

        answer = zip([int(i) for i in downloads], subs, info)
        answer.sort()
        answer.reverse()

        return answer

    except:
        Log("Exception in search_subtitles")
        return []

def download_subtitle(crl, hashcode, folder):
    global Log

    try:
        crl.get('info.php?d=%s&c=1' % hashcode)
        data = crl.body()

        sub_file_name = tempfile.mktemp()
        out = open(sub_file_name, "wb")
        out.write(data)
        out.close()

        return sub_file_name, crl.info()['effective-url']
    except:
        Log("Exception in download_subtitle")
        return None, None

def unzip_file(filename, path, outfiles):
    global Log

    Log("unzip file: %s" % filename)

    zf = zipfile.ZipFile(filename)
    namelist = zf.namelist()
    lines = filter( lambda x: not x.endswith( '/' ), namelist )

    lines = [line for line in lines if line.lower().endswith(".srt")]
    lines.sort()
    outfiles.sort()

    i = 0
    for i in range(len(outfiles)):
        subtitle = lines[i]
        for sub in lines:
            if outfiles[i].lower() in sub.lower():
                subtitle = sub
                break

        out = open(os.path.join(path, outfiles[i] + ".srt"), 'wb' )
        out.write(zf.read(subtitle))
        out.flush()
        out.close()

def unrar_file(filename, path, outfiles):
    global Log

    Log("unrar file: %s" % filename)

    cmd = "unrar vb %s" % filename
    pout, pin = popen2.popen2(cmd)
    lines = pout.read().split("\n")
    pout.close()
    pin.close()

    lines = [line for line in lines if line.lower().endswith(".srt")]
    lines.sort()
    outfiles.sort()

    i = 0
    for i in range(len(outfiles)):
        subtitle = lines[i]
        for sub in lines:
            if outfiles[i].lower() in sub.lower():
                subtitle = sub
                break

        cmd = 'unrar e -o+ "%s" "%s" "%s" >/dev/null' % (filename, subtitle, path)
        os.system(cmd)
        Log("cmd: %s" % cmd)
        subtitle = os.path.basename(subtitle)

        if outfiles[i] + ".srt" != subtitle:
            Log("%s != %s" % (outfiles[i] + ".srt", subtitle))
            Log("path: %s" % path)
            os.rename(os.path.join(path, subtitle),
                      os.path.join(path, outfiles[i] + ".srt"))

def remove_cron_entry(cmdline, cron_user):
    global Log

    Log("removing cron entry: %s" % cmdline)

    ct = CronTab(user=cron_user)
    for entry in ct.find_command(cmdline):
        ct.lines.remove(entry)
        ct.crons.remove(entry)

    ct.write()

def add_cron_entry(time, cmdline, cron_user):
    global Log

    if not time:
        return

    Log("adding cron entry: %s" % cmdline)

    ct = CronTab(user=cron_user)
    entry = ct.find_command(cmdline)

    if entry:
        Log("cron entry already added: %s" % cmdline)
        return

    entry = ct.new(command=cmdline)
    entry.hour().every(time)
    entry.minute().on(0)
    ct.write()

def check_release_path(path):
    release = os.path.basename(path)
    outfiles = [release]
    folder = None

    if os.path.exists(path):
        if os.path.isfile(path):
            folder = os.path.dirname(path)
            release = os.path.basename(path)
            release = os.path.splitext(release)[0]
            outfiles = [release]
        else:
            folder = path
            outfiles = [f[:-4] for f in os.listdir(path)
                        if f.lower().endswith(".avi") or f.lower().endswith(".mkv")]

            if path.endswith(os.path.pathsep):
                release = os.path.basename(path[:-1])
            else:
                release = os.path.basename(path)

    Log("release: %s" % release)
    Log("folder: %s" % folder)
    Log("outfiles: %s" % outfiles)

    return release, outfiles, folder

def print_subtitle_info(sub):
    Log("\nSubtitle: %s" % sub[2][INFO_RELEASE])
    Log("    movie: %s" % sub[2][INFO_NAME])
    Log("    filme: %s" % sub[2][INFO_NAME_PT])
    Log("    cds: %s" % sub[2][INFO_NUMCDS])
    Log("    fps: %s" % sub[2][INFO_FPS])
    Log("    size: %s" % sub[2][INFO_SIZE])
    Log("    downloads: %s" % sub[2][INFO_DOWNLOADS])
    Log("    flag: %s" % sub[2][INFO_FLAG])

def start_encoder(folder, mconf):
    global Log

    to_encode = mconf['ENCODE_DIR']
    link = os.path.join(to_encode, os.path.basename(folder))

    Log("Creating encoder link %s" % link)
    if os.path.exists(link):
        Log("Link %s already created. Aborting encoder" % link)
        return

    os.symlink(folder, link)
    if not is_encoder_running(mconf):
        Log("Running encoder link")
        run_encoder(to_encode)
    else:
        Log("Encoder already running")

def run_getsub(folder, cron, encode, log):
    log("Running getsub %s %s %s" % (folder, cron, encode))
    if encode:
        os.spawnl(os.P_NOWAIT, "/usr/bin/getsub", "/usr/bin/getsub", "-e", "-k %s" % cron, folder)
    else:
        os.spawnl(os.P_NOWAIT, "/usr/bin/getsub", "/usr/bin/getsub", "-k %s" % cron, folder)

def subtitle(path, mconf, cron, encode, log = print_std):
    global Log

    Log = log
    if encode:
        cmdline = "getsub -e "
    else:
        cmdline = "getsub "

    if cron:
        cmdline += "-k %d %s" % (cron, path)
    else:
        cmdline += "%s" % path

    release, outfiles, folder = check_release_path(path)
    if not folder:
        folder = mconf['TMP_DIR']

    crl = curl.Curl('http://legendas.tv')
    crl.set_verbosity(0)

    if not login_legendas_tv (crl, mconf['SUB_USER'], mconf['SUB_PASSWD']):
        Log("Logon error")
        add_cron_entry(cron, cmdline, mconf['CRON_USER'])
        return False

    Log("Logon ok")
    subtitles = search_subtitle(crl, release, mconf['LANGUAGE'])
    if not len(subtitles):
        Log("No subtitles found")
        add_cron_entry(cron, cmdline, mconf['CRON_USER'])
        return False

    Log("%d subtitles found" % len(subtitles))
    for sub in subtitles:
        if sub[2][INFO_NUMCDS] == "%d" % len(outfiles):
            print_subtitle_info(sub)

            filename, url = download_subtitle(crl, sub[1], folder)
            if not filename or not url:
                Log("Cannot download subtitle.")
                add_cron_entry(cron, cmdline, mconf['CRON_USER'])
                return False

            Log("Subtitle saved in %s" % filename)
            if url.lower().endswith(".zip"):
                unzip_file(filename, folder, outfiles)
            elif url.lower().endswith(".rar"):
                unrar_file(filename, folder, outfiles)
            else:
                Log("Unknown format file %s", url)

            if len(outfiles) == 1:
                Log("Appending subtitle to encode.opts")
                sub = os.path.join(folder, outfiles[0] + ".srt")
                os.system('echo "-sub %s" >> %s/encode.opts' % (sub, folder))

            Log("Removing temporary files: %s" % filename)
            os.remove(filename)

            remove_cron_entry(cmdline, mconf['CRON_USER'])
            for f in outfiles:
                change_owner(os.path.join(folder, f + ".srt"), mconf['HOST_USER'])

            if encode:
                start_encoder(folder, mconf)

            return True

    Log("No subtitles match, but this subtitles are available")
    for sub in subtitles:
        print_subtitle_info(sub)

    add_cron_entry(cron, cmdline, mconf['CRON_USER'])

    return False

def search_results(path, mconf, log):
    global Log

    Log = log
    release, outfiles, folder = check_release_path(path)
    crl = curl.Curl('http://legendas.tv')
    crl.set_verbosity(0)

    if not login_legendas_tv (crl, mconf['SUB_USER'], mconf['SUB_PASSWD']):
        Log("Logon error")
        return False

    Log("Logon ok")
    subtitles = search_subtitle(crl, release, mconf['LANGUAGE'])
    if not len(subtitles):
        Log("No subtitles found")
        return False

    Log("%d subtitles found" % len(subtitles))
    for sub in subtitles:
        print_subtitle_info(sub)
